package engineer.view.database.schema;

import design_patterns.command.CommandState;
import engineer.reverse.schema.RevertSchema;
import fx.FX;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Font;
import mysql.Column;
import mysql.Schema;
import mysql.Table;

import static javafx.scene.text.FontWeight.BOLD;
import static javafx.scene.text.FontWeight.NORMAL;


/**
 * Created by nuno-rafael-figueiredo on 23-03-2014.
 */
public class SchemaController extends BorderPane {
    @FXML
    private TableView<Table> tablesView;

    @FXML
    private TableColumn<Table, String> tableNameCol;

    @FXML
    private TableView<Column> columnsView;

    @FXML
    private TableColumn<Column, String> columnNameCol;

    @FXML
    private TableColumn<Column, String> columnTypeCol;

    @FXML
    private TableColumn<Column, Boolean> columnIsNullableCol;

    @FXML
    private TableColumn<Column, Column.Key> columnKeyCol;

    @FXML
    private TableColumn<Column, String> columnDefaultValueCol;

    @FXML
    private TableColumn<Column, String> columnReferencesCol;

    private Schema schema;

    public SchemaController() {
        FX.load(this);
    }

    @FXML
    private void initialize(){
        tablesView.getSelectionModel().selectedItemProperty().addListener((value, before, after) -> onSelect(after));

        tableNameCol.setCellValueFactory(new PropertyValueFactory<>("name"));

        columnNameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
        columnNameCol.setCellFactory(column -> new TableCell<Column, String>() {
            @Override
            protected void updateItem(String name, boolean empty) {
                if (getTableRow() == null || getTableRow().getItem() == null || name == null) {
                    setText("");
                    setTooltip(null);
                    super.updateItem(name, empty);
                    return;
                }
                super.updateItem(name, empty);
                Column column = (Column) getTableRow().getItem();
                setText(name);
                setFont(Font.font(null, column.isPrimary() ? BOLD : NORMAL, -1));
            }
        });

        columnTypeCol.setCellValueFactory(new PropertyValueFactory<>("type"));
        columnIsNullableCol.setCellValueFactory(new PropertyValueFactory<>("isNullable"));

        columnKeyCol.setCellValueFactory(new PropertyValueFactory<>("key"));
        columnDefaultValueCol.setCellValueFactory(new PropertyValueFactory<>("defaultValue"));

        columnReferencesCol.setCellFactory(column -> new TableCell<Column, String>(){
            @Override
            protected void updateItem(String text, boolean empty) {
                if (empty) {
                    setText("");
                    setTooltip(null);
                    super.updateItem(text, true);

                    return;
                }

                Column column = (Column) getTableRow().getItem();

                final Column.Reference reference = column.getReference();
                if (reference == null){
                    setText("");
                    setTooltip(null);
                    super.updateItem(text, true);

                    return;
                }

                setText(reference.getTable().getName());
            }
        });
    }

    private void onSelect(Table table) {
        if (table == null) columnsView.getItems().clear();
        else columnsView.setItems(table.getColumnList());
    }

    public void setSchema(Schema schema) {
        this.schema = schema;
        tablesView.setItems(schema.getTables().getList());
        schema.extract();
    }

    public void revert(ChangeListener<CommandState> listener) {
        new RevertSchema(schema)
                .onFinish(listener)
                .execute();
    }

    @Override
    public String toString() {
        return schema.toString();
    }
}
